<template>
  <div class="yard-view" :data-block="yardData?.yardId">
    <!--堆场-->
    <div v-if="yardData" class="yard-container" :class="{ 'view-mode': isEditMode, 'edit-mode': isEditMode, 'selected': isSelected }" @dblclick="handleDoubleClick" @mousedown="handleMouseDown" @click="handleYardClick">
      <!--堆场号-->
      <h2 class="yard-title">{{ yardData.yardId }}</h2>
      <!--堆场图-->
      <div
          class="yard-grid"
          ref="yardGrid"
          :class="{ 'view-mode': isEditMode }"
      >
        <!-- 排号 -->
        <div class="yard-row" v-for="row in (yardData?.rowCount || 0)" :key="row">
          <div
              class="bay-number"
              :class="{ 'empty': !shouldShowRow(row) }"
              :style="rowHeaderStyle"
          >
            {{ shouldShowRow(row) ? formatRowNumber(row) : '' }}
          </div>

          <!-- 单个位置 -->
          <div
              v-for="bay in (yardData?.bayCount || 0)"
              :key="bay"
              class="grid-cell"
              :class="{ 'bay-column-hovered': hoveredBay === bay }"
              :style="cellStyle"
              :data-col="getDisplayBay(bay)"
              :data-row="getDisplayRow(row)"
          ></div>
        </div>

        <!-- 贝号 -->
        <div class="column-headers">
          <!--堆场号-->
          <div class="bay-header" :style="blockStyle">{{ yardData?.yardId }}</div>
          <div
              v-for="bay in (yardData?.bayCount || 0)"
              :key="bay"
              class="column-header"
              :class="{ 
                'empty': !shouldShowBay(bay),
                'bay-hovered': hoveredBay === bay
              }"
              :style="bayHeaderStyle"
              @mouseenter="onBayHeaderHover(bay)"
              @mouseleave="onBayHeaderLeave"
              @dblclick="showBayViewer(bay)"
          >
            {{ shouldShowBay(bay) ? formatBayNumber(bay) : '' }}
          </div>
        </div>

        <!-- 集装箱覆盖层 -->
        <div
          v-for="container in activeContainers"
          :key="`${container.bay}-${container.row}-${container.tier || 1}`"
          class="container-overlay"
          :class="getContainerOverlayClass(container)"
          :style="getContainerOverlayStyle(container)"
          :title="getContainerTooltip(container)"
          @mouseenter="onContainerOverlayHover(container)"
          @mouseleave="onContainerOverlayLeave(container)"
          @click="onContainerOverlayClick(container)"
        >
        </div>

        <!-- 计划区域覆盖层 -->
        <div
          v-for="plan in activePlans"
          :key="plan.planId"
          class="plan-overlay"
          :class="getPlanOverlayClass(plan)"
          :style="getPlanOverlayStyle(plan)"
          :title="getPlanTooltip(plan)"
          @mouseenter="onPlanOverlayHover(plan)"
          @mouseleave="onPlanOverlayLeave(plan)"
          @click="onPlanOverlayClick(plan)"
        >
          <div class="plan-id-label">{{ plan.planId }}</div>
          <!-- L形箭头路径 -->
          <svg
            class="path-arrow"
            :style="getPathArrowStyle(plan)"
            :viewBox="getPathArrowViewBox(plan)"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              :d="getPathArrowPath(plan)"
              class="arrow-path"
              :class="getPathArrowClass(plan)"
            />
            <polygon
              :points="getPathArrowHead(plan)"
              class="arrow-head"
              :class="getPathArrowClass(plan)"
            />
          </svg>
        </div>

        <!-- 加锁区域覆盖层 -->
        <div
          v-for="lock in activeLocks"
          :key="lock.lockId"
          class="lock-overlay"
          :class="getLockOverlayClass(lock)"
          :style="getLockOverlayStyle(lock)"
          :title="getLockTooltip(lock)"
          @mouseenter="onLockOverlayHover(lock)"
          @mouseleave="onLockOverlayLeave(lock)"
          @click="onLockOverlayClick(lock)"
        >
          <!-- 锁图标 -->
          <div class="lock-icon">🔒</div>
        </div>
      </div>
      
      <!-- 编辑模式下的旋转控制UI -->
      <div v-if="isEditMode && isSelected" class="rotation-controls" @click.stop>
        <div class="rotation-info">
          <span class="rotation-label">旋转角度:</span>
          <span class="rotation-value">{{ yardData.rotation || 0 }}°</span>
        </div>
        <div class="rotation-buttons">
          <button @click.stop="rotateYard(-90)" @mousedown.stop class="rotation-btn" title="逆时针旋转90度">↺</button>
          <button @click.stop="rotateYard(90)" @mousedown.stop class="rotation-btn" title="顺时针旋转90度">↻</button>
        </div>
      </div>
    </div>

    <!-- 加载状态 -->
    <div v-else class="yard-loading">
      <div class="loading-spinner"></div>
      <p>正在加载堆场数据...</p>
    </div>

  </div>
</template>

<script>
import dataApiService from "@/services/api.js";

export default {
  name: 'YardView',
  props: {
    // 堆场数据对象，包含堆场ID、贝数、排数等信息
    yardData: {
      type: Object,
      required: false,
      default: null,
      validator(value) {
        // 允许null值，但如果是对象则必须包含必要的属性
        return value === null || (typeof value === 'object' && value.yardId)
      }
    },
    // 控制集装箱显示状态
    showContainers: {
      type: Boolean,
      default: true
    },
    // 控制堆场计划显示状态
    showPlans: {
      type: Boolean,
      default: true
    },
    showLocks: {
      type: Boolean,
      default: true
    },
    // 控制是否为编辑模式
    isEditMode: {
      type: Boolean,
      default: false
    },
    // 控制是否被选中
    isSelected: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // 集装箱数据数组，存储当前堆场的所有集装箱信息
      containerData: [],
      // 堆场计划数据数组，存储当前堆场的所有计划信息
      yardPlans: [],
      // 堆场加锁数据数组，存储当前堆场的所有加锁信息
      yardLocks: [],
      // 堆场配置参数
      config: {
        // 基础尺寸
        cellWidth: 60,        // 单元格宽度（像素）
        cellHeight: 30,       // 单元格高度（像素）

        // 标题尺寸（固定常量）
        bayNumberHeight: 30,  // 贝号高度（像素）
        rowNumberWidth: 40,   // 排号宽度（像素）

        // 显示控制
        intervalDisplayBays: false,  // 是否间隔显示贝号
        intervalDisplayRows: false,  // 是否间隔显示排号
      },
      // 计划覆盖层悬停状态
      hoveredPlanId: null,    // 当前悬停的计划ID
      selectedPlanId: null,   // 当前选中的计划ID
      // 加锁覆盖层悬停状态
      hoveredLockId: null,    // 当前悬停的加锁ID
      selectedLockId: null,   // 当前选中的加锁ID
      // 集装箱覆盖层悬停状态
      hoveredContainerId: null,    // 当前悬停的集装箱ID
      selectedContainerId: null,   // 当前选中的集装箱ID
      // 贝号悬浮状态
      hoveredBay: null             // 当前悬浮的贝号
    }
  },
  computed: {
    /**
     * 获取活跃的集装箱列表（用于v-for渲染）
     * 只显示每个位置最顶层的集装箱
     * @returns {Array} 过滤后的活跃集装箱数组
     */
    activeContainers() {
      if (!this.showContainers || !this.yardData) {
        return []
      }

      // 获取当前堆场的所有集装箱
      const yardContainers = this.containerData.filter(container =>
        container.block === this.yardData.yardId
      )

      // 按位置分组，每个位置只显示最顶层的集装箱
      const positionMap = new Map()

      yardContainers.forEach(container => {
        const positionKey = `${container.bay}-${container.row}`
        const tier = container.tier || 1

        if (!positionMap.has(positionKey) || tier > (positionMap.get(positionKey).tier || 1)) {
          positionMap.set(positionKey, container)
        }
      })

      return Array.from(positionMap.values())
    },

    /**
     * 获取活跃的计划列表（用于v-for渲染）
     * @returns {Array} 过滤后的活跃计划数组
     */
    activePlans() {
      if (!this.showPlans) {
        return []
      }
      return this.yardPlans
    },
    /**
     * 获取活跃的加锁列表（用于v-for渲染）
     * @returns {Array} 过滤后的活跃加锁数组
     */
    activeLocks() {
      if (!this.showLocks) {
        return []
      }
      return this.yardLocks
    },

    // 堆场号样式计算属性
    blockStyle() {
      if (!this.yardData) return {}
      return { height: `${this.config.bayNumberHeight}px`, width: `${this.config.rowNumberWidth}px` }
    },
    // 贝号列宽度样式计算属性
    bayHeaderStyle() {
      return { height: `${this.config.bayNumberHeight}px`, width: `${this.config.cellWidth}px` }
    },
    // 排号行高度样式计算属性
    rowHeaderStyle() {
      return { height: `${this.config.cellHeight}px`, width: `${this.config.rowNumberWidth}px` }
    },

    // 网格单元格样式计算属性，设置单元格的宽高和布局
    cellStyle() {
      return {
        width: `${this.config.cellWidth || 60}px`,
        height: `${this.config.cellHeight || 30}px`,
        flex: 'none'  // 防止单元格被拉伸
      }
    }
  },
  // 组件挂载后加载集装箱数据和堆场计划
  async mounted() {
    console.log('YardBlock mounted, yardData:', this.yardData)
    await this.loadContainerData()
    await this.loadYardPlans()
    await this.loadYardLocks()
  },
  // 监听堆场ID变化，重新加载对应的集装箱数据和堆场计划
  watch: {
    'yardData.yardId': {
      handler() {
        this.loadContainerData()
        this.loadYardPlans()
        this.loadYardLocks()
      }
    }
  },
  methods: {
    /**
     * 工具方法：将实际贝号转换为网格列位置
     * @param {number} bay - 实际贝号
     * @returns {number} 网格列位置
     */
    bayToGridCol(bay) {
      return Math.floor((bay + 1) / 2)
    },

    /**
     * 工具方法：根据方向调整贝号显示
     * @param {number} bay - 原始贝号
     * @param {number} maxBay - 最大贝号
     * @returns {number} 调整后的贝号
     */
    adjustBayByDirection(bay, maxBay) {
      if (this.yardData?.bayDirection === 0) {
        return maxBay - bay + 1
      }
      return bay
    },

    /**
     * 工具方法：根据方向调整排号显示
     * @param {number} row - 原始排号
     * @param {number} maxRow - 最大排号
     * @returns {number} 调整后的排号
     */
    adjustRowByDirection(row, maxRow) {
      if (this.yardData?.rowDirection === 0) {
        return maxRow - row + 1
      }
      return row
    },

    /**
     * 工具方法：计算点的X坐标
     * @param {number} gridCol - 网格列位置
     * @param {number} minGridCol - 最小网格列
     * @param {number} maxGridCol - 最大网格列
     * @returns {number} X坐标
     */
    calculatePointX(gridCol, minGridCol, maxGridCol) {
      if (this.yardData?.bayDirection === 0) {
        return (maxGridCol - gridCol + 1) * this.config.cellWidth - this.config.cellWidth / 2
      } else {
        return (gridCol - minGridCol) * this.config.cellWidth + this.config.cellWidth / 2
      }
    },

    /**
     * 工具方法：计算点的Y坐标
     * @param {number} row - 排号
     * @param {number} minRow - 最小排号
     * @param {number} maxRow - 最大排号
     * @returns {number} Y坐标
     */
    calculatePointY(row, minRow, maxRow) {
      if (this.yardData?.rowDirection === 0) {
        return (maxRow - row + 1) * this.config.cellHeight - this.config.cellHeight / 2
      } else {
        return (row - minRow) * this.config.cellHeight + this.config.cellHeight / 2
      }
    },

    /**
     * 加载集装箱数据
     * 优先加载特定堆场的数据文件，如果不存在则从通用数据文件中过滤
     */
    async loadContainerData() {
      // 如果没有堆场ID，直接返回
      if (!this.yardData.yardId) return

      try {
        this.containerData = await dataApiService.getContainerData(this.yardData.yardId)
      } catch (error) {
        console.error('加载集装箱数据失败:', error)
        this.containerData = []
      }
    },
    /**
     * 加载堆场计划数据
     * 优先加载特定堆场的计划文件，如果不存在则从通用计划文件中过滤
     */
    async loadYardPlans() {
      // 如果没有堆场ID，直接返回
      if (!this.yardData.yardId) return

      try {
        this.yardPlans = await dataApiService.getYardPlans(this.yardData.yardId)
      } catch (error) {
        console.error('加载堆场计划失败:', error)
        this.yardPlans = []
      }
    },
    /**
     * 加载堆场加锁数据
     * 优先加载特定堆场的加锁文件，如果不存在则从通用加锁文件中过滤
     */
    async loadYardLocks() {
      // 如果没有堆场ID，直接返回
      if (!this.yardData.yardId) return

      try {
        this.yardLocks = await dataApiService.getYardLocks(this.yardData.yardId)
      } catch (error) {
        console.error(`加载堆场 ${this.yardData.yardId} 加锁数据失败:`, error)
        this.yardLocks = []
      }
    },

    /**
     * 判断是否应该显示指定贝号
     * @param {number} bay - 贝号
     * @returns {boolean} 是否显示该贝号
     */
    shouldShowBay(bay) {
      // 根据配置决定是否间隔显示贝号
      if (this.config.intervalDisplayBays) {
        // 间隔显示：只显示奇数贝号
        return bay % 2 === 1
      }
      // 连续显示：显示所有贝号
      return true
    },

    /**
     * 判断是否应该显示指定排
     * @param {number} row - 排号
     * @returns {boolean} 是否显示该排
     */
    shouldShowRow(row) {
      // 根据配置决定是否间隔显示排号
      if (this.config.intervalDisplayRows) {
        // 间隔显示：只显示奇数排号
        return row % 2 === 1
      }
      // 连续显示：显示所有排号
      return true
    },


    /**
     * 格式化贝号显示
     * @param {number} bay - 贝号
     * @returns {string} 格式化后的贝号（补零到3位，始终显示奇数）
     */
    formatBayNumber(bay) {
      if (!this.yardData) return ''
      // 贝号始终显示奇数（001, 003, 005...）
      const actualBay = bay * 2 - 1
      const maxBay = this.yardData.bayCount * 2 - 1
      const adjustedBay = this.adjustBayByDirection(actualBay, maxBay)

      return adjustedBay.toString().padStart(3, '0')
    },
    /**
     * 格式化排号显示
     * @param {number} row - 排号
     * @returns {string} 格式化后的排号（补零到2位）
     */
    formatRowNumber(row) {
      if (!this.yardData) return ''
      const adjustedRow = this.adjustRowByDirection(row, this.yardData.rowCount)
      return adjustedRow.toString().padStart(2, '0')
    },

    /**
     * 获取显示的贝号（用于data-col属性）
     * @param {number} bay - 网格贝号
     * @returns {number} 显示的贝号
     */
    getDisplayBay(bay) {
      if (!this.yardData) return bay
      const actualBay = bay * 2 - 1
      const maxBay = this.yardData.bayCount * 2 - 1
      return this.adjustBayByDirection(actualBay, maxBay)
    },

    /**
     * 获取显示的排号（用于data-row属性）
     * @param {number} row - 网格排号
     * @returns {number} 显示的排号
     */
    getDisplayRow(row) {
      if (!this.yardData) return row
      return this.adjustRowByDirection(row, this.yardData.rowCount)
    },


    /**
     * 获取集装箱覆盖层的样式类
     * @param {Object} container - 集装箱对象
     * @returns {string} CSS类名字符串
     */
    getContainerOverlayClass(container) {
      const classes = []

      // 添加偶数贝标识类
      if (container.bay % 2 === 0) {
        classes.push('even-bay-container')
      }

      // 添加悬停状态类
      const containerId = `${container.bay}-${container.row}-${container.tier || 1}`
      if (this.hoveredContainerId === containerId) {
        classes.push('container-hovered')
      }

      // 添加选中状态类
      if (this.selectedContainerId === containerId) {
        classes.push('container-selected')
      }

      return classes.join(' ')
    },
    /**
     * 获取计划覆盖层的样式类
     * @param {Object} plan - 计划对象
     * @returns {string} CSS类名字符串
     */
    getPlanOverlayClass(plan) {
      const classes = []
      // 移除基于planType的样式类，改为使用统一的plan-overlay类
      classes.push('plan-overlay')

      // 添加悬停状态类
      if (this.hoveredPlanId === plan.planId) {
        classes.push('plan-hovered')
      }

      // 添加选中状态类
      if (this.selectedPlanId === plan.planId) {
        classes.push('plan-selected')
      }

      return classes.join(' ')
    },

    /**
     * 集装箱覆盖层的位置计算
     * @param {Object} container - 集装箱对象
     * @returns {Object} 样式对象
     */
    getContainerOverlayStyle(container) {
      // 计算集装箱位置
      const bay = container.bay
      const row = container.row

      // 网格边框宽度
      const yardGridBorder = 2
      // 排号宽度
      const rowNumberWidth = this.config.rowNumberWidth
      // 单元格高度
      const cellHeight = this.config.cellHeight


      let left, width

      // 检查是否是偶数贝集装箱
      if (bay % 2 === 0) {
        // 偶数贝集装箱占用两个相邻的奇数贝单元格
        // 例如：贝号10占用贝号9和贝号11的单元格
        const prevOddBay = bay - 1  // 前面的奇数贝

        // 计算前面奇数贝的网格列位置
        const prevGridCol = this.bayToGridCol(prevOddBay)

        // 计算覆盖层位置（从前面奇数贝开始，宽度为两个单元格）
        left = rowNumberWidth + (prevGridCol - 1) * this.config.cellWidth
        width = this.config.cellWidth * 2 // 两个单元格的宽度
      } else {
        // 奇数贝集装箱只占用一个单元格
        const gridCol = this.bayToGridCol(bay)
        left = rowNumberWidth + (gridCol - 1) * this.config.cellWidth
        width = this.config.cellWidth
      }

      // 根据贝循方向调整left位置
      if (this.yardData?.bayDirection === 0) {
        // 沿负方向增加，需要从右侧开始计算
        const totalWidth = this.yardData.bayCount * this.config.cellWidth
        left = (rowNumberWidth + totalWidth) - (left - rowNumberWidth) - width
      }

      // 根据排循方向调整top位置(表头线的宽度 + 单元格总高度 + 单元格线的总宽度)
      let top = yardGridBorder +
          ((row - 1) * cellHeight) +
          ((row - 2) * 0.6)

      if (this.yardData?.rowDirection === 0) {
        // 沿负方向增加，需要从底部开始计算(堆场总高度 - 距离底部高度 + 单元格线总宽度)
        const totalHeight = this.yardData.rowCount * cellHeight
        top = (yardGridBorder + totalHeight) - row * cellHeight + ((this.yardData.rowCount - row) * 0.6)
      }


      // 设置集装箱为第二层
      const zIndex = 2

      // 基础样式对象
      const baseStyle = {
        position: 'absolute',
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${cellHeight}px`,
        zIndex: zIndex
      }

      // 如果集装箱有颜色，添加动态颜色样式
      if (container.color) {
        const color = container.color

        // 生成渐变背景
        baseStyle.background = `linear-gradient(145deg, ${color} 0%, ${this.darkenColor(color, 0.1)} 25%, ${this.darkenColor(color, 0.2)} 75%, ${this.darkenColor(color, 0.3)} 100%)`

        // 生成动态阴影效果
        const rgb = this.hexToRgb(color)
        if (rgb) {
          baseStyle.boxShadow = `
            0 6px 16px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3),
            0 3px 8px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.2),
            inset 0 2px 0 rgba(255, 255, 255, 0.4),
            inset 0 -2px 0 rgba(0, 0, 0, 0.15),
            inset 1px 0 0 rgba(255, 255, 255, 0.2),
            inset -1px 0 0 rgba(0, 0, 0, 0.1)
          `
        }
      }

      return baseStyle
    },
    /**
     * 计划覆盖层的位置计算
     * @param {Object} plan - 计划对象
     * @returns {Object} 样式对象
     */
    getPlanOverlayStyle(plan) {
      // 计算计划区域的位置和尺寸
      const startBay = plan.startBay
      const endBay = plan.endBay
      const startRow = plan.startRow
      const endRow = plan.endRow

      // 将实际贝号转换为网格列位置
      // 实际贝号1,3,5,7...对应网格列1,2,3,4...
      const startGridCol = this.bayToGridCol(startBay)
      const endGridCol = this.bayToGridCol(endBay)

      // 网格边框宽度
      const yardGridBorder = 2
      // 排号宽度
      const rowNumberWidth = this.config.rowNumberWidth
      // 单元格高度
      const cellHeight = this.config.cellHeight

      // 计算覆盖层的实际范围（使用最小值和最大值）
      const minGridCol = Math.min(startGridCol, endGridCol)
      const maxGridCol = Math.max(startGridCol, endGridCol)
      const minRow = Math.min(startRow, endRow)
      const maxRow = Math.max(startRow, endRow)

      // 使用网格列位置计算覆盖层位置
      let left = rowNumberWidth +
          (minGridCol - 1) * this.config.cellWidth
      let top = yardGridBorder +
          ((minRow - 1) * this.config.cellHeight) +
          ((minRow - 2) * 0.6)
      const width = (maxGridCol - minGridCol + 1) * this.config.cellWidth
      const height = (maxRow - minRow + 1) * this.config.cellHeight

      // 根据贝循方向调整left位置
      if (this.yardData?.bayDirection === 0) {
        // 沿负方向增加，需要从右侧开始计算
        const totalWidth = this.yardData.bayCount * this.config.cellWidth
        left = (rowNumberWidth + totalWidth) - (left - rowNumberWidth) - width
      }

      // 根据排循方向调整top位置
      if (this.yardData?.rowDirection === 0) {
        // 沿负方向增加，需要从底部开始计算(堆场总高度 - 距离底部高度 - 自身高度 + 单元格线总宽度)
        const totalHeight = this.yardData.rowCount * this.config.cellHeight
        top = (yardGridBorder + totalHeight) - ((startRow - 1) * cellHeight) - height + ((this.yardData.rowCount - endRow) * 0.6)
      }

      // 基础样式对象
      const baseStyle = {
        position: 'absolute',
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${height}px`,
        zIndex: 3
      }

      // 如果计划有颜色，添加动态颜色样式
      if (plan.color) {
        const color = plan.color
        const rgb = this.hexToRgb(color)

        if (rgb) {
          // 检查状态
          const isHovered = this.hoveredPlanId === plan.planId
          const isSelected = this.selectedPlanId === plan.planId
          
          if (isSelected) {
            // 选中状态：使用纯色背景，增强边框和阴影
            baseStyle.background = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.4)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.9)`
            baseStyle.boxShadow = `
              0 8px 25px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.4),
              0 4px 15px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3),
              0 2px 8px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.2),
              0 0 0 2px rgba(255, 255, 255, 0.4)
            `
            // 设置CSS变量用于脉冲动画
            baseStyle['--pulse-color'] = color
            baseStyle['--pulse-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`
          } else if (isHovered) {
            // 悬停时使用纯色背景
            baseStyle.background = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.8)`
            baseStyle.boxShadow = `
              0 12px 35px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.25),
              0 6px 20px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.15),
              0 2px 8px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.1),
              0 0 0 1px rgba(255, 255, 255, 0.3),
              inset 0 1px 0 rgba(255, 255, 255, 0.2)
            `
          } else {
            // 正常状态使用渐变背景
            baseStyle.background = `linear-gradient(135deg,
              rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.2) 0%,
              rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.1) 50%,
              rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.15) 100%)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.6)`
            baseStyle.boxShadow = `
              0 4px 12px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.12),
              0 2px 6px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.08),
              0 1px 3px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.05)
            `
          }
        }
      }

      return baseStyle
    },




    /**
     * 处理计划覆盖层鼠标进入事件
     * @param {Object} plan - 计划对象
     */
    onPlanOverlayHover(plan) {
      if (this.isEditMode) {
        return;
      }
      this.hoveredPlanId = plan.planId
    },
    /**
     * 处理计划覆盖层鼠标离开事件
     */
    onPlanOverlayLeave() {
      if (this.isEditMode) {
        return;
      }
      this.hoveredPlanId = null
    },
    /**
     * 处理计划覆盖层点击事件
     * @param {Object} plan - 计划对象
     */
    onPlanOverlayClick(plan) {
      if (this.isEditMode) {
        return;
      }
      // 切换选中状态
      if (this.selectedPlanId === plan.planId) {
        this.selectedPlanId = null
      } else {
        this.selectedPlanId = plan.planId
      }

      // 发射事件给父组件
      this.$emit('plan-selected', {
        yardId: this.yardData?.yardId,
        plan: plan,
        isSelected: this.selectedPlanId === plan.planId
      })
    },

    /**
     * 获取加锁覆盖层的样式类
     * @param {Object} lock - 加锁对象
     * @returns {string} CSS类名字符串
     */
    getLockOverlayClass(lock) {
      const classes = []
      classes.push('lock-overlay')

      // 添加悬停状态类
      if (this.hoveredLockId === lock.lockId) {
        classes.push('lock-hovered')
      }

      // 添加选中状态类
      if (this.selectedLockId === lock.lockId) {
        classes.push('lock-selected')
      }

      return classes.join(' ')
    },

    /**
     * 加锁覆盖层的位置计算
     * @param {Object} lock - 加锁对象
     * @returns {Object} 样式对象
     */
    getLockOverlayStyle(lock) {
      // 计算加锁区域的位置和尺寸
      const bay = lock.bay
      const row = lock.row

      // 将实际贝号转换为网格列位置
      // 实际贝号1,3,5,7...对应网格列1,2,3,4...
      const gridCol = Math.floor((bay + 1) / 2)

      // 网格边框宽度
      const yardGridBorder = 2
      // 排号宽度
      const rowNumberWidth = this.config.rowNumberWidth
      // 单元格高度
      const cellHeight = this.config.cellHeight

      // 使用网格列位置计算覆盖层位置
      let left = rowNumberWidth +
          (gridCol - 1) * this.config.cellWidth
      let top = yardGridBorder +
          ((row - 1) * this.config.cellHeight) +
          ((row - 2) * 0.6)
      const width = this.config.cellWidth
      const height = this.config.cellHeight

      // 根据贝循方向调整left位置
      if (this.yardData?.bayDirection === 0) {
        // 沿负方向增加，需要从右侧开始计算
        const totalWidth = this.yardData.bayCount * this.config.cellWidth
        left = (rowNumberWidth + totalWidth) - (left - rowNumberWidth) - width
      }

      // 根据排循方向调整top位置
      if (this.yardData?.rowDirection === 0) {
        // 沿负方向增加，需要从底部开始计算(堆场总高度 - 距离底部高度 + 单元格线总宽度)
        const totalHeight = this.yardData.rowCount * this.config.cellHeight
        top = (yardGridBorder + totalHeight) - row * cellHeight + ((this.yardData.rowCount - row) * 0.6)
      }

      // 基础样式对象
      const baseStyle = {
        position: 'absolute',
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${height}px`,
        zIndex: 2
      }

      // 如果加锁有颜色，添加动态颜色样式
      if (lock.color) {
        const color = lock.color
        const rgb = this.hexToRgb(color)

        if (rgb) {
          // 检查状态
          const isHovered = this.hoveredLockId === lock.lockId
          const isSelected = this.selectedLockId === lock.lockId
          
          if (isSelected) {
            // 选中状态：使用纯色背景，增强边框和阴影
            baseStyle.background = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.4)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.9)`
            baseStyle.boxShadow = `
              0 8px 25px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.4),
              0 4px 15px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3),
              0 2px 8px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.2),
              0 0 0 2px rgba(255, 255, 255, 0.4)
            `
            // 设置CSS变量用于脉冲动画
            baseStyle['--pulse-color'] = color
            baseStyle['--pulse-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`
          } else if (isHovered) {
            // 悬停时使用纯色背景
            baseStyle.background = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.8)`
            // 优化阴影效果：多层阴影营造立体感
            baseStyle.boxShadow = `
              0 12px 35px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.25),
              0 6px 20px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.15),
              0 2px 8px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.1),
              0 0 0 1px rgba(255, 255, 255, 0.3),
              inset 0 1px 0 rgba(255, 255, 255, 0.2)
            `
          } else {
            // 正常状态使用纯色背景
            baseStyle.background = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.1)`
            baseStyle.borderColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.6)`
            // 优化正常状态阴影：更柔和的阴影效果
            baseStyle.boxShadow = `
              0 4px 12px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.12),
              0 2px 6px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.08),
              0 1px 3px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.05)
            `
          }
        }
      }

      return baseStyle
    },

    /**
     * 处理加锁覆盖层鼠标进入事件
     * @param {Object} lock - 加锁对象
     */
    onLockOverlayHover(lock) {
      this.hoveredLockId = lock.lockId
    },
    /**
     * 处理加锁覆盖层鼠标离开事件
     */
    onLockOverlayLeave() {
      this.hoveredLockId = null
    },
    /**
     * 处理加锁覆盖层点击事件
     * @param {Object} lock - 加锁对象
     */
    onLockOverlayClick(lock) {
      if (this.isEditMode) {
        return;
      }
      // 切换选中状态
      if (this.selectedLockId === lock.lockId) {
        this.selectedLockId = null
      } else {
        this.selectedLockId = lock.lockId
      }

      // 发射事件给父组件
      this.$emit('lock-selected', {
        yardId: this.yardData?.yardId,
        lock: lock,
        isSelected: this.selectedLockId === lock.lockId
      })
    },


    /**
     * 处理集装箱覆盖层鼠标进入事件
     * @param {Object} container - 集装箱对象
     */
    onContainerOverlayHover(container) {
      if (this.isEditMode) {
        return;
      }
      this.hoveredContainerId = `${container.bay}-${container.row}-${container.tier || 1}`
    },
    /**
     * 处理集装箱覆盖层鼠标离开事件
     */
    onContainerOverlayLeave() {
      if (this.isEditMode) {
        return;
      }
      this.hoveredContainerId = null
    },
    /**
     * 处理集装箱覆盖层点击事件
     * @param {Object} container - 集装箱对象
     */
    onContainerOverlayClick(container) {
      if (this.isEditMode) {
        return;
      }
      const containerId = `${container.bay}-${container.row}-${container.tier || 1}`

      // 切换选中状态
      if (this.selectedContainerId === containerId) {
        this.selectedContainerId = null
      } else {
        this.selectedContainerId = containerId
      }

      // 发射事件给父组件
      this.$emit('container-selected', {
        yardId: this.yardData?.yardId,
        container: container,
        isSelected: this.selectedContainerId === containerId
      })
    },


    /**
     * 处理双击事件(弹出详情框)
     * 在查看模式下双击堆场时显示详细信息模态框
     * @param {MouseEvent} event - 鼠标事件对象
     */
    handleDoubleClick(event) {
      // 只有在查看模式下才响应双击事件
      if (this.isEditMode) {
        return
      }

      // 防止在标题或其他非堆场区域触发
      const forbiddenSelectors = [
        '.bay-header',
        '.column-header',
        '.bay-number',
        '.yard-title'
      ]

      const isForbiddenArea = forbiddenSelectors.some(selector =>
          event.target.closest(selector)
      )

      if (isForbiddenArea) {
        return
      }

      // 发射事件给父组件，请求显示详细信息模态框
      this.$emit('show-yard-detail', {
        yardId: this.yardData?.yardId,
        yardData: this.yardData,
        containerData: this.containerData,
        yardPlans: this.yardPlans,
        yardLocks: this.yardLocks
      })
    },

    /**
     * 处理鼠标按下事件
     * 在编辑模式下开始拖拽堆场
     * @param {MouseEvent} event - 鼠标事件对象
     */
    handleMouseDown(event) {
      // 只有在编辑模式下才响应拖拽
      if (!this.isEditMode) {
        return
      }

      // 防止在标题或其他非堆场区域触发拖拽
      const forbiddenSelectors = [
        '.bay-header',
        '.column-header',
        '.bay-number',
        '.yard-title',
        '.rotation-controls',
        '.rotation-btn'
      ]

      const isForbiddenArea = forbiddenSelectors.some(selector =>
          event.target.closest(selector)
      )

      if (isForbiddenArea) {
        return
      }

      // 发射拖拽开始事件给父组件
      this.$emit('start-drag', event, this.yardData?.yardId)
    },


    /**
     * 获取指定位置的所有集装箱
     * @param {number} bay - 贝号
     * @param {number} row - 排号
     * @returns {Array} 该位置的所有集装箱数组
     */
    getContainersAtPosition(bay, row) {
      if (!this.yardData) return []
      return this.containerData.filter(container =>
        container.block === this.yardData.yardId &&
        container.bay === bay &&
        container.row === row
      ).sort((a, b) => (a.tier || 1) - (b.tier || 1))
    },
    /**
     * 获取集装箱的悬浮提示信息
     * @param {Object} container - 集装箱对象
     * @returns {string} 提示信息
     */
    getContainerTooltip(container) {
      const bay = container.bay
      const row = container.row

      // 获取该位置的所有集装箱
      const containersAtPosition = this.getContainersAtPosition(bay, row)
      const totalTiers = containersAtPosition.length

      return `位置: ${bay}贝${row}排\n总层数: ${totalTiers}层`
    },
    /**
     * 获取堆场计划的悬浮提示信息
     * @param {Object} plan - 计划对象
     * @returns {string} 提示信息
     */
    getPlanTooltip(plan) {
      const description = plan.description || '无描述'
      const createdAt = plan.createdAt ? new Date(plan.createdAt).toLocaleString() : '未知时间'

      // 计算计划区域大小
      const bayCount = plan.endBay - plan.startBay + 1
      const rowCount = plan.endRow - plan.startRow + 1
      const areaSize = `${bayCount}贝 × ${rowCount}排`

      return `计划ID: ${plan.planId}\n区域: ${plan.startBay}-${plan.endBay}贝 ${plan.startRow}-${plan.endRow}排\n大小: ${areaSize}\n创建时间: ${createdAt}\n描述: ${description}`
    },
    /**
     * 获取堆场加锁的悬浮提示信息
     * @param {Object} lock - 加锁对象
     * @returns {string} 提示信息
     */
    getLockTooltip(lock) {
      const description = lock.description || '无描述'
      const lockTime = lock.lockTime ? new Date(lock.lockTime).toLocaleString() : '未知时间'
      const lockOperator = lock.lockOperator || '未知操作员'
      const lockReason = lock.lockReason || '未知原因'

      return `加锁ID: ${lock.lockId}\n位置: ${lock.bay}贝${lock.row}排\n加锁时间: ${lockTime}\n操作员: ${lockOperator}\n加锁原因: ${lockReason}\n描述: ${description}`
    },


    /**
     * 获取路径箭头的样式
     * @param {Object} plan - 计划对象
     * @returns {Object} 样式对象
     */
    getPathArrowStyle(plan) {
      // 计算覆盖层的尺寸
      const startGridCol = this.bayToGridCol(plan.startBay)
      const endGridCol = this.bayToGridCol(plan.endBay)
      const width = Math.abs(endGridCol - startGridCol + 1) * this.config.cellWidth
      const height = Math.abs(plan.endRow - plan.startRow + 1) * this.config.cellHeight

      const baseStyle = {
        position: 'absolute',
        top: '0',
        left: '0',
        width: `${width}px`,
        height: `${height}px`,
        pointerEvents: 'none',
        zIndex: 4
      }

      // 如果计划有颜色，为箭头添加动态颜色
      if (plan.color) {
        const color = plan.color
        const rgb = this.hexToRgb(color)

        if (rgb) {
          // 为箭头路径和头部设置颜色
          baseStyle['--arrow-color'] = color
          baseStyle['--arrow-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`
        }
      }

      return baseStyle
    },
    /**
     * 获取路径箭头的视图框
     * @param {Object} plan - 计划对象
     * @returns {string} SVG viewBox字符串
     */
    getPathArrowViewBox(plan) {
      const startGridCol = this.bayToGridCol(plan.startBay)
      const endGridCol = this.bayToGridCol(plan.endBay)
      const width = Math.abs(endGridCol - startGridCol + 1) * this.config.cellWidth
      const height = Math.abs(plan.endRow - plan.startRow + 1) * this.config.cellHeight

      return `0 0 ${width} ${height}`
    },
    /**
     * 获取路径箭头的CSS类
     * @returns {string} CSS类名字符串
     */
    getPathArrowClass() {
      const classes = []
      // 移除基于planType的颜色类，改为使用统一的arrow-default类
      classes.push('arrow-default')

      return classes.join(' ')
    },
    /**
     * 获取路径箭头的路径数据
     * @param {Object} plan - 计划对象
     * @returns {string} SVG路径字符串
     */
    getPathArrowPath(plan) {
      // 计算覆盖层的尺寸和边界
      const startGridCol = this.bayToGridCol(plan.startBay)
      const endGridCol = this.bayToGridCol(plan.endBay)
      const minGridCol = Math.min(startGridCol, endGridCol)
      const maxGridCol = Math.max(startGridCol, endGridCol)
      const minRow = Math.min(plan.startRow, plan.endRow)
      const maxRow = Math.max(plan.startRow, plan.endRow)

      // 计算三个关键点的网格位置
      const startGridColPos = startGridCol
      const endGridColPos = endGridCol
      const startRowPos = plan.startRow
      const endRowPos = plan.endRow

      // 计算三个点的相对坐标（相对于覆盖层左上角）
      let point1X, point1Y  // 开始点：开始贝，开始排
      let point2X, point2Y  // 拐点：开始贝，结束排
      let point3X, point3Y  // 结束点：结束贝，结束排

      // 计算开始点（开始贝，开始排）的中心坐标
      point1X = this.calculatePointX(startGridColPos, minGridCol, maxGridCol)
      point1Y = this.calculatePointY(startRowPos, minRow, maxRow)

      // 计算拐点（开始贝，结束排）的中心坐标
      point2X = this.calculatePointX(startGridColPos, minGridCol, maxGridCol)
      point2Y = this.calculatePointY(endRowPos, minRow, maxRow)

      // 计算结束点（结束贝，结束排）的中心坐标
      point3X = this.calculatePointX(endGridColPos, minGridCol, maxGridCol)
      point3Y = this.calculatePointY(endRowPos, minRow, maxRow)

      // 创建L形路径：从开始点 -> 拐点 -> 结束点
      return `M ${point1X} ${point1Y} L ${point2X} ${point2Y} L ${point3X} ${point3Y}`
    },
    /**
     * 获取路径箭头的箭头头部
     * @param {Object} plan - 计划对象
     * @returns {string} SVG多边形点字符串
     */
    getPathArrowHead(plan) {
      // 计算覆盖层的尺寸和边界
      const startGridCol = this.bayToGridCol(plan.startBay)
      const endGridCol = this.bayToGridCol(plan.endBay)
      const minGridCol = Math.min(startGridCol, endGridCol)
      const maxGridCol = Math.max(startGridCol, endGridCol)
      const minRow = Math.min(plan.startRow, plan.endRow)
      const maxRow = Math.max(plan.startRow, plan.endRow)

      // 计算结束点（结束贝，结束排）的中心坐标 - 作为箭头中心点
      const endGridColPos = endGridCol
      const endRowPos = plan.endRow

      const centerX = this.calculatePointX(endGridColPos, minGridCol, maxGridCol)
      const centerY = this.calculatePointY(endRowPos, minRow, maxRow)

      // 计算箭头方向 - 朝向第二个点（拐点）和第三个点（结束点）的延伸方向
      // 计算拐点（第二个点）的坐标
      const cornerX = this.calculatePointX(startGridCol, minGridCol, maxGridCol)
      const cornerY = this.calculatePointY(endRowPos, minRow, maxRow)

      // 计算箭头方向向量：从拐点指向结束点的方向
      const deltaX = centerX - cornerX
      const deltaY = centerY - cornerY
      const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY)

      // 归一化方向向量
      const dirX = length > 0 ? deltaX / length : 0
      const dirY = length > 0 ? deltaY / length : 0

      // 箭头尺寸
      const arrowSize = 10
      const arrowWidth = 8

      // 计算箭头的三个顶点
      // 箭头尖端朝向第二个点和第三个点的延伸方向
      const tipX = centerX + dirX * arrowSize
      const tipY = centerY + dirY * arrowSize

      // 箭头底部的两个点
      const baseX1 = centerX - dirY * arrowWidth / 2
      const baseY1 = centerY + dirX * arrowWidth / 2
      const baseX2 = centerX + dirY * arrowWidth / 2
      const baseY2 = centerY - dirX * arrowWidth / 2

      // 返回三角形的三个顶点坐标
      return `${tipX},${tipY} ${baseX1},${baseY1} ${baseX2},${baseY2}`
    },


    /**
     * 将16进制颜色变暗
     * @param {string} hexColor - 16进制颜色代码
     * @param {number} amount - 变暗程度 (0-1)
     * @returns {string} 变暗后的16进制颜色代码
     */
    darkenColor(hexColor, amount) {
      // 移除#号
      const hex = hexColor.replace('#', '')

      // 转换为RGB
      const r = parseInt(hex.substr(0, 2), 16)
      const g = parseInt(hex.substr(2, 2), 16)
      const b = parseInt(hex.substr(4, 2), 16)

      // 变暗
      const newR = Math.floor(r * (1 - amount))
      const newG = Math.floor(g * (1 - amount))
      const newB = Math.floor(b * (1 - amount))

      // 转换回16进制
      const toHex = (n) => {
        const hex = n.toString(16)
        return hex.length === 1 ? '0' + hex : hex
      }

      return `#${toHex(newR)}${toHex(newG)}${toHex(newB)}`
    },
    /**
     * 将16进制颜色转换为RGB对象
     * @param {string} hexColor - 16进制颜色代码
     * @returns {Object|null} RGB对象 {r, g, b} 或 null
     */
    hexToRgb(hexColor) {
      // 移除#号
      const hex = hexColor.replace('#', '')

      // 检查格式
      if (hex.length !== 6) {
        return null
      }

      // 转换为RGB
      const r = parseInt(hex.substr(0, 2), 16)
      const g = parseInt(hex.substr(2, 2), 16)
      const b = parseInt(hex.substr(4, 2), 16)

      return { r, g, b }
    },

    /**
     * 处理贝号头部鼠标进入事件
     * @param {number} bay - 网格贝号
     */
    onBayHeaderHover(bay) {
      if (this.isEditMode) {
        return
      }
      this.hoveredBay = bay
    },

    /**
     * 处理贝号头部鼠标离开事件
     */
    onBayHeaderLeave() {
      if (this.isEditMode) {
        return
      }
      this.hoveredBay = null
    },


    /**
     * 显示单贝图查看器
     * @param {number} bay - 贝号
     */
    showBayViewer(bay) {
      if (this.isEditMode) {
        console.log('编辑模式下，不显示单贝图')
        return
      }

      // 将网格贝号转换为实际贝号（网格贝号1,2,3...对应实际贝号1,3,5...）
      const actualBay = bay * 2 - 1
      const maxBay = this.yardData.bayCount * 2 - 1
      const adjustedBay = this.adjustBayByDirection(actualBay, maxBay)

      console.log('双击贝号:', bay, '实际贝号:', adjustedBay, '堆场:', this.yardData?.yardId)

      // 发射事件给父组件，请求显示单贝图
      this.$emit('show-bay-viewer', {
        yardId: this.yardData?.yardId,
        bayNumber: adjustedBay,
        bayCount: this.yardData?.bayCount,
        rowCount: this.yardData?.rowCount,
        tierCount: this.yardData?.tierCount || 4,
        containerData: this.containerData,
        yardPlans: this.yardPlans,
        yardLocks: this.yardLocks
      })

      console.log('已发射 show-bay-viewer 事件')
    },

    /**
     * 刷新当前堆场的数据
     * 重新加载集装箱数据和计划数据
     */
    async refreshData() {
      console.log(`开始刷新堆场 ${this.yardData?.yardId} 的数据...`)

      try {
        // 重新加载集装箱数据
        await this.loadContainerData()

        // 重新加载计划数据
        await this.loadYardPlans()

        // 重新加载加锁数据
        await this.loadYardLocks()

        // 强制重新渲染
        this.$forceUpdate()

        console.log(`堆场 ${this.yardData?.yardId} 数据刷新完成`)
      } catch (error) {
        console.error(`刷新堆场 ${this.yardData?.yardId} 数据失败:`, error)
      }
    },

    /**
     * 处理堆场点击事件
     * 在编辑模式下选择堆场
     * @param {MouseEvent} event - 鼠标事件对象
     */
    handleYardClick(event) {
      // 只有在编辑模式下才响应点击选择
      if (!this.isEditMode) {
        return
      }

      // 防止在标题或其他非堆场区域触发选择
      const forbiddenSelectors = [
        '.bay-header',
        '.column-header',
        '.bay-number',
        '.yard-title',
        '.rotation-controls',
        '.rotation-btn'
      ]

      const isForbiddenArea = forbiddenSelectors.some(selector =>
          event.target.closest(selector)
      )

      if (isForbiddenArea) {
        return
      }

      // 发射选择事件给父组件
      this.$emit('yard-selected', this.yardData?.yardId)
    },

    /**
     * 旋转堆场
     * @param {number} angle - 旋转角度（度）
     */
    rotateYard(angle) {
      if (!this.yardData) return

      // 计算新的旋转角度，不直接修改props
      let newRotation = (this.yardData.rotation || 0) + angle
      
      // 保持角度在0-360度范围内
      if (newRotation < 0) {
        newRotation += 360
      }
      if (newRotation >= 360) {
        newRotation = newRotation % 360
      }

      console.log(`堆场 ${this.yardData.yardId} 旋转到 ${newRotation} 度`)

      // 发射旋转事件给父组件，让父组件处理数据更新和保存
      this.$emit('yard-rotated', {
        yardId: this.yardData.yardId,
        rotation: newRotation
      })
    }

  }
}
</script>

<style scoped>
/* 通用样式变量和基础设置 */
* {
  box-sizing: border-box !important;
}

.yard-view {
  font-family: 'Courier New', monospace;
  position: relative;
  z-index: 1;
}

.yard-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  border-radius: 8px;
  /*方便观察单个堆场,后续不需要可删除*/
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  padding: 10px;
  transition: box-shadow 0.3s ease, transform 0.2s ease;
  cursor: pointer;
  transform-origin: center center;
}

/* 堆场区域悬停阴影加深效果 */
.yard-container:hover {
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2), 0 4px 12px rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

/* 查看模式下的双击提示 */
.yard-container {
  position: relative;
}

.yard-container.view-mode::after {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 8px 16px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 100;
  white-space: nowrap;
}

/* 只在查看模式下显示提示 */
.yard-container.view-mode:hover::after {
  opacity: 1;
}

.yard-title {
  font-size: 24px;
  font-weight: bold;
  color: #333;
  margin: 0;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}


/* 堆场网格样式 */
.yard-grid {
  border: 2px solid #333;
  background: #fff;
  width: fit-content;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  position: relative;
  z-index: 1;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

/* 查看模式样式 */
.yard-grid.view-mode {
  pointer-events: none;
}

.yard-grid.view-mode .grid-cell {
  cursor: default;
}

/* 编辑模式样式 */
.yard-container.edit-mode {
  cursor: grab;
  transition: all 0.2s ease;
}

.yard-container.edit-mode:hover {
  cursor: grab;
  transform: scale(1.02);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2), 0 4px 12px rgba(0, 0, 0, 0.15);
}

.yard-container.edit-mode:active {
  cursor: grabbing;
}

/* 编辑模式下禁用堆场内部元素的交互 */
.yard-container.edit-mode .yard-grid {
  pointer-events: none;
}

.yard-container.edit-mode .container-overlay,
.yard-container.edit-mode .plan-overlay {
  pointer-events: none;
}

.column-headers {
  display: flex;
  border-top: 2px solid #333;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

/* 通用头部样式 */
.bay-header,
.column-header {
  background: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  padding: 8px 0;
}

.bay-header {
  border-right: 2px solid #333;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.column-header {
  border-right: 1px solid #ccc;
}

.column-header:last-child {
  border-right: none;
}

.column-header.empty {
  background-color: #f9f9f9;
}

/* 贝号悬浮高亮效果 */
.column-header.bay-hovered {
  background: linear-gradient(135deg, #007bff 0%, #0056b3 100%) !important;
  color: white !important;
  box-shadow: 0 4px 12px rgba(0, 123, 255, 0.4);
  z-index: 10;
}

/* 行样式 */
.yard-row {
  display: flex;
  border-bottom: 1px solid #ccc;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

.yard-row:last-child {
  border-bottom: 2px solid #333;
}

/* 贝号样式 */
.bay-number {
  border-right: 2px solid #333;
  background: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  padding: 8px 0;
  font-size: 12px;
}

.bay-number.empty {
  background-color: #f9f9f9;
}

/* 网格单元格样式 */
.grid-cell {
  border-right: 1px solid #eee;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  overflow: hidden;
  transform-origin: center center;
  background-image:
    radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 1px, transparent 1px),
    radial-gradient(circle at 80% 80%, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
  background-size: 8px 8px, 12px 12px;
}

/* 贝位区域悬停效果 */
.grid-cell:hover {
  background-color: rgba(0, 123, 255, 0.1) !important;
  border-color: rgba(0, 123, 255, 0.3) !important;
  transform: scale(1.05);
  z-index: 10;
}

.grid-cell:last-child {
  border-right: none;
}

/* 贝号整列高亮效果 */
.grid-cell.bay-column-hovered {
  background-color: rgba(25, 118, 210, 0.1) !important;
  border-color: rgba(25, 118, 210, 0.3) !important;
  transition: all 0.2s ease;
}

/* 集装箱覆盖层样式 */
.container-overlay {
  position: absolute;
  border: none;
  border-radius: 0;
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.15),
    0 2px 4px rgba(0, 0, 0, 0.1);
  transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  cursor: pointer;
  pointer-events: auto;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  background-image:
    radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 1px, transparent 1px),
    radial-gradient(circle at 80% 80%, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
  background-size: 8px 8px, 12px 12px;
  z-index: 1;
}

/* 集装箱覆盖层颜色样式 - 现在完全基于JSON中的16进制颜色代码动态生成 */

/* 偶数贝集装箱特殊样式 - 大箱样式 */
.container-overlay.even-bay-container {
  border: none;
  border-radius: 0;
  box-shadow:
    0 8px 20px rgba(0, 0, 0, 0.25),
    0 4px 10px rgba(0, 0, 0, 0.15),
    inset 0 3px 0 rgba(255, 255, 255, 0.4),
    inset 0 -3px 0 rgba(0, 0, 0, 0.15),
    inset 2px 0 0 rgba(255, 255, 255, 0.25),
    inset -2px 0 0 rgba(0, 0, 0, 0.1);
}

/* 奇数贝集装箱特殊样式 - 小箱样式 */
.container-overlay:not(.even-bay-container) {
  border-radius: 0;
  box-shadow:
    0 5px 12px rgba(0, 0, 0, 0.2),
    0 2px 6px rgba(0, 0, 0, 0.1),
    inset 0 2px 0 rgba(255, 255, 255, 0.4),
    inset 0 -2px 0 rgba(0, 0, 0, 0.15),
    inset 1px 0 0 rgba(255, 255, 255, 0.25),
    inset -1px 0 0 rgba(0, 0, 0, 0.1);
}

/* 集装箱覆盖层悬停效果 */
.container-overlay.container-hovered {
  transform: scale(1.05) translateY(-3px);
  z-index: 3;
  filter: brightness(1.15) saturate(1.3) contrast(1.05);
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.2),
    0 6px 16px rgba(0, 0, 0, 0.15),
    inset 0 3px 0 rgba(255, 255, 255, 0.5),
    inset 0 -3px 0 rgba(0, 0, 0, 0.2);
}

/* 大箱悬停效果 */
.container-overlay.even-bay-container.container-hovered {
  transform: scale(1.05) translateY(-4px);
  box-shadow:
    0 16px 40px rgba(0, 0, 0, 0.3),
    0 8px 20px rgba(0, 0, 0, 0.2),
    inset 0 4px 0 rgba(255, 255, 255, 0.5),
    inset 0 -4px 0 rgba(0, 0, 0, 0.2),
    inset 3px 0 0 rgba(255, 255, 255, 0.3),
    inset -3px 0 0 rgba(0, 0, 0, 0.15);
}

/* 小箱悬停效果 */
.container-overlay:not(.even-bay-container).container-hovered {
  transform: scale(1.05) translateY(-3px);
  box-shadow:
    0 12px 28px rgba(0, 0, 0, 0.25),
    0 6px 14px rgba(0, 0, 0, 0.15),
    inset 0 3px 0 rgba(255, 255, 255, 0.5),
    inset 0 -3px 0 rgba(0, 0, 0, 0.2),
    inset 2px 0 0 rgba(255, 255, 255, 0.3),
    inset -2px 0 0 rgba(0, 0, 0, 0.15);
}

/* 集装箱覆盖层选中状态 */
.container-overlay.container-selected {
  animation: containerPulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  border-width: 3px;
  z-index: 4;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

.container-overlay.container-selected::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  right: -4px;
  bottom: -4px;
  border: 2px solid;
  border-radius: 6px;
  opacity: 0.6;
  animation: containerPulseRing 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  pointer-events: none;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* 集装箱脉冲动画关键帧 */
@keyframes containerPulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.01);
    opacity: 0.98;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes containerPulseRing {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  60% {
    transform: scale(1.06);
    opacity: 0.15;
  }
  100% {
    transform: scale(1.12);
    opacity: 0;
  }
}

/* 计划覆盖层样式 */
.plan-overlay {
  position: absolute;
  border: 2px solid;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  pointer-events: auto;
  z-index: 2;
}


/* 计划覆盖层基础样式 - 现在通过JavaScript动态设置颜色 */
.plan-overlay {
  border: 2px solid;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  pointer-events: auto;
  z-index: 2;
}

/* 加锁覆盖层基础样式 */
.lock-overlay {
  border: 2px solid rgba(255, 152, 0, 0.6);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  pointer-events: auto;
  z-index: 2;
}

.lock-overlay .lock-icon {
  font-size: 24px;
  color: rgba(255, 152, 0, 0.8);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  animation: lockPulse 2s ease-in-out infinite;
}

/* 计划ID标签样式 - 在覆盖层中居中 */
.plan-overlay .plan-id-label {
  font-size: 10px;
  font-weight: bold;
  color: #2c3e50;
  background: rgba(255, 255, 255, 0.95);
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);
  pointer-events: none;
  z-index: 3;
}

/* L形路径箭头样式 */
.path-arrow {
  overflow: visible;
}

.arrow-path {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}

.arrow-head {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}

/* 默认箭头样式 - 现在通过CSS变量支持动态颜色 */
.arrow-path.arrow-default {
  stroke: var(--arrow-color, #34495e);
}

.arrow-head.arrow-default {
  fill: var(--arrow-color, #34495e);
}

/* 计划覆盖层悬停效果 */
.plan-overlay.plan-hovered {
  transform: scale(1.05) translateY(-2px);
  box-shadow:
    0 8px 25px rgba(0, 0, 0, 0.3),
    0 4px 12px rgba(0, 0, 0, 0.2),
    0 0 0 1px rgba(255, 255, 255, 0.2);
  z-index: 5;
  filter: brightness(1.1) saturate(1.2);
  border-width: 3px;
}

/* 计划覆盖层悬停效果 - 现在通过JavaScript动态设置颜色 */
.plan-overlay.plan-hovered {
  transform: scale(1.05) translateY(-2px);
  box-shadow:
    0 8px 25px rgba(0, 0, 0, 0.3),
    0 4px 12px rgba(0, 0, 0, 0.2),
    0 0 0 1px rgba(255, 255, 255, 0.2);
  z-index: 5;
  filter: brightness(1.1) saturate(1.2);
  border-width: 3px;
}

/* 加锁覆盖层悬停效果 */
.lock-overlay.lock-hovered {
  transform: scale(1.05) translateY(-2px);
  box-shadow:
    0 8px 25px rgba(0, 0, 0, 0.3),
    0 4px 12px rgba(0, 0, 0, 0.2),
    0 0 0 1px rgba(255, 255, 255, 0.2);
  z-index: 5;
  filter: brightness(1.1) saturate(1.2);
  border-width: 3px;
}


/* 计划覆盖层选中状态 */
.plan-overlay.plan-selected {
  animation: planPulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  border-width: 3px;
  z-index: 6;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

.plan-overlay.plan-selected::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  right: -4px;
  bottom: -4px;
  border: 2px solid var(--pulse-color, #007bff);
  border-radius: 6px;
  opacity: 0.6;
  animation: planPulseRing 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  pointer-events: none;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* 计划覆盖层选中状态 - 现在通过JavaScript动态设置颜色 */
.plan-overlay.plan-selected {
  animation: planPulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  border-width: 3px;
  z-index: 6;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* 加锁覆盖层选中状态 */
.lock-overlay.lock-selected {
  animation: planPulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  border-width: 3px;
  z-index: 6;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

.lock-overlay.lock-selected::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  right: -4px;
  bottom: -4px;
  border: 2px solid #FF9800;
  border-radius: 6px;
  opacity: 0.6;
  animation: planPulseRing 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  pointer-events: none;
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* 脉冲动画关键帧 */
@keyframes planPulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.01);
    opacity: 0.98;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes planPulseRing {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  60% {
    transform: scale(1.06);
    opacity: 0.15;
  }
  100% {
    transform: scale(1.12);
    opacity: 0;
  }
}




/* 加载状态样式 */
.yard-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px;
  color: #666;
  font-size: 14px;
}

.loading-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #007bff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 16px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.yard-loading p {
  margin: 0;
  font-family: 'Courier New', monospace;
}

/* 旋转控制UI样式 */
.rotation-controls {
  position: absolute;
  top: -50px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 8px 12px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 1000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.2);
  pointer-events: auto; /* 确保可以接收鼠标事件 */
}

.rotation-info {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 500;
}

.rotation-label {
  color: #ccc;
}

.rotation-value {
  color: #00ff00;
  font-weight: bold;
  font-family: 'Courier New', monospace;
}

.rotation-buttons {
  display: flex;
  gap: 5px;
}

.rotation-btn {
  width: 24px;
  height: 24px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.1);
  color: white;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: bold;
  transition: all 0.2s ease;
  user-select: none;
}

.rotation-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.5);
  transform: scale(1.1);
}

.rotation-btn:active {
  transform: scale(0.95);
  background: rgba(255, 255, 255, 0.3);
}

/* 选中状态的堆场样式 */
.yard-container.selected {
  box-shadow: 0 0 0 3px #9C27B0, 0 8px 25px rgba(156, 39, 176, 0.3);
  transform: scale(1.02);
}

.yard-container.selected .yard-title {
  color: #9C27B0;
  font-weight: bold;
}
</style>
